
#include "PestilenceDuplicate.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/CreatureMgr.h"
#include "Common/TableData/MonsterMonsterCfg.h"
#include "Character/monster/MonsterRefCfg.h"
#include "Character/SkillPart.h"
#include "Mail/GMailManager.h"
#include "base/core/Utf8AndWideChar.h"
#include "Common/TableData/TeleportBornCfg.h"
#include "Character/HuoYueDuPart.h"
#include "Effect/EffectMgr.h"
#include "Character/drop/DropMgr.h"

PestilenceDuplicate::PestilenceDuplicate()
{
	m_byType = (int8_t)EDuplicateType::EDuplicateType_Pestilence;
	m_cfg.Clear();
	m_mapCharCamp.clear();
	m_setDownChar.clear();
	m_mapCharInjectNum.clear();
	m_maxInjectNum = 0;
	m_setInitEnter.clear();
}

PestilenceDuplicate::~PestilenceDuplicate()
{

}


//初始化
bool PestilenceDuplicate::Init(uint32_t nDuplicateID, uint32_t nSceneID, IBrushMonster *pBrush)
{
	if (Duplicate::Init(nDuplicateID, nSceneID, pBrush))
	{
		if (g_GetDuplicateMgr()->GetPestilenceLuaCfg(m_cfg))
		{
			SetPestilenceContiSec(m_cfg.contiTime);
			return true;
		}
	}

	return false;
}
//
void PestilenceDuplicate::UnInit()
{
	Duplicate::UnInit();
	m_cfg.Clear();
	m_mapCharCamp.clear();
	m_setDownChar.clear();
	m_mapCharInjectNum.clear();
	m_maxInjectNum = 0;
	m_setInitEnter.clear();
}


//获取瘟疫之战持续时间和变身ID
void PestilenceDuplicate::GetPestilenceContiAndTransID(int32_t &contiSec, int32_t &injectTransId, int32_t &surviveTransId)
{
	contiSec = m_cfg.contiTime;
	injectTransId = m_cfg.injectReplaceId;
	surviveTransId = m_cfg.surviveReplaceId;
}
//获取玩家阵营
int8_t PestilenceDuplicate::GetDupCharCamp(CharIDType charId)
{
	return CharCamp(charId);
}

//获取瘟疫之战中 感染者和生还者数量
void PestilenceDuplicate::GetPestilenceNum(int32_t &injectNum, int32_t &surviveNum)
{
	injectNum = CampNum(EDupCampType_Inject);
	surviveNum = CampNum(EDupCampType_Survive);
}

//生物进入场景
void PestilenceDuplicate::OnCreatureEnter(Creature *pCreature)
{
	if (nullptr == pCreature)
	{
		return;
	}
	if (CREATURE_PLAYER == pCreature->CreatureKind())
	{
		//
		CharIDType cid = pCreature->GetCid();
		m_setInitEnter.insert(cid);
		//
		NotifyCampNum();

		//进入副本，瘟疫之战活跃度
		HuoYueDuPart*pHuoyuePart = dynamic_cast<HuoYueDuPart*>(pCreature->GetPart(PART_HUOYUEDU));
		if (nullptr != pHuoyuePart)
		{
			pHuoyuePart->AddHuoYueDuRecord(HYDT_ACTIVITY_PESTILENCE);
		}
	}
}

//生物离开副本
void PestilenceDuplicate::OnPlayerLeave(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	//删除玩家
	int8_t byCamp = CharCamp(pPlayer->GetCid());
	DelCharCamp(pPlayer->GetCid());
	//
	if ((int8_t)EDuplicateState::EDuplicateState_Begin == GetDuplicateState())
	{
		if (nullptr != pPlayer)
		{
			//玩家离开，通知其他玩家 AAAXXX逃离了对抗
			Duplicate_NotifyLeaveRsp rsp;
			rsp.set_charid(pPlayer->GetCid());
			rsp.set_name(pPlayer->GetName());
			BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_LEAVE, &rsp);


			//通知 生还者，感染者数量
			NotifyCampNum();

			//离线 / 主动退出的生还者，当其离线 / 主动退出时，此时所有感染者的所感染生还者数量 + 1d
			if (byCamp == EDupCampType_Survive)
			{
				SET_UINT64 setChar;
				setChar.clear();
				GetCampChar(EDupCampType_Inject, setChar);
				SET_UINT64::iterator iter = setChar.begin();
				for (; iter != setChar.end(); ++iter)
				{
					AddCharInject((*iter), 1);
				}
			}			
		}
	}	
}

//是否能进入
bool PestilenceDuplicate::OnCanEnter(Creature *pCreature)
{
	_UNUSE(pCreature);
	return true;
}

//进入区域
bool PestilenceDuplicate::OnEnterArea(uint32_t nAreaID)
{
	_UNUSE(nAreaID);
	return true;
}
//复活
void PestilenceDuplicate::OnRelive(Player *pPlayer, int8_t byType)
{
	_UNUSE(pPlayer);
	_UNUSE(byType);
}

//主动离开副本之前 的处理 
void PestilenceDuplicate::OnActiveBeforeLeave(CharIDType cid)
{
	Duplicate::OnActiveBeforeLeave(cid);
}

//进入副本成功
void PestilenceDuplicate::OnEnterSuccess(CharIDType charId)
{
	int8_t resCamp = EDupCampType_None;
	MAP_UINT64_UINT32::iterator iterBorn = m_paramEx.mapCharBorn.find(charId);
	if (iterBorn != m_paramEx.mapCharBorn.end())
	{
		uint32_t bornId = iterBorn->second;
		const TeleportBornCfgInfo *pTeleportBornCfg = g_GetTeleportBornCfgTable()->GetTeleportBornCfgInfo(bornId);
		if (nullptr != pTeleportBornCfg)
		{

			if (ETeleportCamp_Inject == pTeleportBornCfg->camp)
			{
				resCamp = EDupCampType_Inject;
			}
			else if (ETeleportCamp_Survive == pTeleportBornCfg->camp)
			{
				resCamp = EDupCampType_Survive;
			}
			else
			{
				LogErrFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess.....pTeleportBornCfg->camp error , dupid:%u ,sceneid:%u, mapid:%u, bornid:%d, camp:%d ", m_nDuplicateID, m_nSceneID, m_nMapID, bornId,pTeleportBornCfg->camp);
			}
			
		}
		else
		{
			LogErrFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess....nullptr == pTeleportBornCfg , dupid:%u ,sceneid:%u, mapid:%u, bornid:%d,", m_nDuplicateID, m_nSceneID, m_nMapID,bornId);
		}
	}
	else
	{
		LogErrFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess....can not find char bornid , dupid:%u ,sceneid:%u, mapid:%u, charid:%lu,", m_nDuplicateID, m_nSceneID, m_nMapID, charId);
	}
	if (EDupCampType_None != resCamp)
	{
		AddCharCamp(charId, resCamp);
		/*int32_t replaceSkillId = m_cfg.surviveReplaceId;
		if (EDupCampType_Inject == resCamp)
		{
			m_maxInjectNum += 1;
			replaceSkillId = m_cfg.injectReplaceId;
		}
		//生还者有初始buff
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			SkillPart *pSkillPart = dynamic_cast<SkillPart*>(pPlayer->GetPart(PART_SKILL));
			if (nullptr != pSkillPart)
			{
				pSkillPart->AddStateBag(replaceSkillId, 1);
			}
			else
			{
				LogDebugFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess .... nullptr == pSkillPart .... cid:%u ,resCamp:%d, duplicateid:%u, sceneid:%u ", charId, resCamp, m_nDuplicateID, m_nSceneID);
			}
		}
		else
		{
			LogDebugFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess .... nullptr == pPlayer .... cid:%u ,resCamp:%d, duplicateid:%u, sceneid:%u ", charId, resCamp, m_nDuplicateID, m_nSceneID);
		}*/

		LogDebugFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess success...cid:%lu ,resCamp:%d, duplicateid:%u, sceneid:%u ", charId, resCamp, m_nDuplicateID, m_nSceneID);
	}
	else
	{
		LogDebugFmtPrint("[logic] PestilenceDuplicate::OnEnterSuccess...EDupCampType_None == resCamp...  cid:%lu ,resCamp:%d, duplicateid:%u, sceneid:%u ", charId, resCamp, m_nDuplicateID, m_nSceneID);
	}
}

void PestilenceDuplicate::AddDown(CharIDType charId)	//添加倒地玩家
{
	m_setDownChar.insert(charId);
}

void PestilenceDuplicate::DelDown(CharIDType charId)	//删除倒地玩家
{
	m_setDownChar.erase(charId);
}

bool PestilenceDuplicate::IsDown(CharIDType charId)		//玩家是否处于倒地状态
{
	SET_UINT64::iterator iter = m_setDownChar.find(charId);
	return (iter != m_setDownChar.end()) ? true : false;
}

int32_t PestilenceDuplicate::CampNum(int8_t camp)		//指定阵营的数量
{
	int32_t nNum = 0;
	MAP_UINT64_INT8::iterator iter = m_mapCharCamp.begin();
	for (; iter != m_mapCharCamp.end(); ++iter)
	{
		if (camp == iter->second)
		{
			nNum += 1;
		}
	}
	return nNum;
}

void PestilenceDuplicate::GetCampChar(int8_t camp, SET_UINT64 &setChar) //获取阵营所有玩家
{
	MAP_UINT64_INT8::iterator iter = m_mapCharCamp.begin();
	for (; iter != m_mapCharCamp.end(); ++iter)
	{
		if (iter->second == camp)
		{
			setChar.insert(iter->first);
		}
	}
}

int8_t PestilenceDuplicate::CharCamp(CharIDType charId)
{
	MAP_UINT64_INT8::iterator iter = m_mapCharCamp.find(charId);
	if (iter != m_mapCharCamp.end())
	{
		return iter->second;
	}
	return EDupCampType_None;
}

bool PestilenceDuplicate::IsInjectCamp(CharIDType charId)//玩家是否是感染者阵营
{
	return (EDupCampType_Inject == CharCamp(charId));
}

bool PestilenceDuplicate::IsSurviveCamp(CharIDType charId)//玩家是否是生还者阵营
{
	return (EDupCampType_Survive == CharCamp(charId));
}

void PestilenceDuplicate::AddCharCamp(CharIDType charId, int8_t camp) //添加玩家阵营
{
	m_mapCharCamp[charId] = camp;
}

void PestilenceDuplicate::DelCharCamp(CharIDType charId)	//删除玩家阵营
{
	m_mapCharCamp.erase(charId);
}

void PestilenceDuplicate::AddCharInject(CharIDType charId,int32_t nNum)		//增加感染者 感染的数量
{
	MAP_UINT64_INT32::iterator iter = m_mapCharInjectNum.find(charId);
	if (iter != m_mapCharInjectNum.end())
	{
		iter->second += nNum;
	}
	else
	{
		m_mapCharInjectNum[charId] = nNum;
	}
}

int32_t PestilenceDuplicate::GetInjectNum(CharIDType charId) //获取玩家把 生还者变成感染者的数量
{
	MAP_UINT64_INT32::iterator iter = m_mapCharInjectNum.find(charId);
	return (iter != m_mapCharInjectNum.end()) ? iter->second : 0;
}

void PestilenceDuplicate::SurviveBeInject(CharIDType charId) //生还者被感染了
{
	if ((int8_t)EDuplicateState::EDuplicateState_Begin == GetDuplicateState())
	{
		return;
	}
	if (!IsSurviveCamp(charId))
	{
		return;
	}
	Player *pPlayer = GetPlayer(charId);
	if (nullptr != pPlayer)
	{
		int32_t replaceFacadeId = m_cfg.surviveReplaceId;
		int32_t replaceSkillId = m_cfg.surviveReplaceSkillId;
		//先移除生还者外观触发器，技能触发器
		if (RET_SUCCESS != g_GetEffectMgr()->RemoveEffect(pPlayer, replaceFacadeId))
		{
			LogErrFmtPrint("[logic] PestilenceDuplicate::SurviveBeInject...RemoveEffect facade.... cid:%lu, dupid:%u, sceneid:%u, replaceFacadeId:%u ", charId,m_nDuplicateID,m_nSceneID,replaceFacadeId);
		}
		if (RET_SUCCESS != g_GetEffectMgr()->RemoveEffect(pPlayer, replaceSkillId))
		{
			LogErrFmtPrint("[logic] PestilenceDuplicate::SurviveBeInject...RemoveEffect skill.... cid:%lu, dupid:%u, sceneid:%u, replaceFacadeId:%u ", charId, m_nDuplicateID, m_nSceneID, replaceSkillId);
		}

		//添加新的 感染者 外观触发器，技能触发器
		replaceFacadeId = m_cfg.injectReplaceId;
		replaceSkillId = m_cfg.injectReplaceSkillId;
		if (RET_SUCCESS != g_GetEffectMgr()->OnEffect(pPlayer, replaceFacadeId))
		{
			LogErrFmtPrint("[logic] PestilenceDuplicate::SurviveBeInject...OnEffect injector facade.... cid:%lu, dupid:%u, sceneid:%u, replaceFacadeId:%u ", charId, m_nDuplicateID, m_nSceneID, replaceFacadeId);
		}
		if (RET_SUCCESS != g_GetEffectMgr()->OnEffect(pPlayer, replaceSkillId))
		{
			LogErrFmtPrint("[logic] PestilenceDuplicate::SurviveBeInject...OnEffect injector skill.... cid:%lu, dupid:%u, sceneid:%u, replaceFacadeId:%u ", charId, m_nDuplicateID, m_nSceneID, replaceSkillId);
		}

		//增加最大感染者数量
		m_maxInjectNum += 1;
		//从阵营删除
		DelCharCamp(charId);
		//加入到感染者阵营
		AddCharCamp(charId, EDupCampType_Inject);
		//通知 生还者和感染者数量变化
		NotifyCampNum();
		//通知玩家改变阵营
		NotifyCharChangeCamp(charId, EDupCampType_Inject);

	}
	else
	{
		LogErrFmtPrint("[logic] PestilenceDuplicate::SurviveBeIject...nullptr == pPlayer ....charid:%lu, dupid:%u, sceneid:%u ", charId, m_nDuplicateID, m_nSceneID);
	}
}

void PestilenceDuplicate::NotifyCampNum()
{
	Duplicate_NotifyCampNumRsp rsp;
	rsp.set_inject_num(CampNum(EDupCampType_Inject));
	rsp.set_survive_num(CampNum(EDupCampType_Survive));
	BroadCastData(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_CAMP_NUM, &rsp);
}

void PestilenceDuplicate::NotifyCharChangeCamp(CharIDType charId, int8_t camp) //通知角色阵营改变
{
	Player *pPlayer = GetPlayer(charId);
	if (nullptr != pPlayer)
	{
		Duplicate_NotifyCampChangeRsp rsp;
		rsp.set_camp(camp);
		pPlayer->SendDataToClient(EMODULE_ID_DUPLICATE, LOGIC_TO_CLIENT_DUPLICATE_NOTIFY_CAMP_CHANGE, &rsp);
	}


}

void PestilenceDuplicate::CheckInitEnter()	//检查初始进入副本的玩家
{
	SET_UINT64::iterator iterCid = m_setInitEnter.begin();
	for (; iterCid != m_setInitEnter.end(); ++iterCid)
	{
		CharIDType cid = (*iterCid);
		Player *pPlayer = GetPlayer(cid);
		if (nullptr != pPlayer)
		{
			//进入瘟疫之战副本，替换外观，替换技能
			int32_t replaceFacaId = m_cfg.surviveReplaceId;
			int32_t replaceSkillId = m_cfg.surviveReplaceSkillId;
			if (IsInjectCamp(cid))
			{
				replaceFacaId = m_cfg.injectReplaceId;
				replaceSkillId = m_cfg.injectReplaceSkillId;
			}
			if (RET_SUCCESS != g_GetEffectMgr()->OnEffect(pPlayer, replaceFacaId))
			{
				LogErrFmtPrint("[logic] PestilenceDuplicate::OnCreatureEnter...oneffect facade error ...cid:%lu, dupid:%u, sceneid:%u, effectid:%u ", cid, m_nDuplicateID, m_nSceneID, replaceFacaId);
			}

			if (RET_SUCCESS != g_GetEffectMgr()->OnEffect(pPlayer, replaceSkillId))
			{
				LogErrFmtPrint("[logic] PestilenceDuplicate::OnCreatureEnter...oneffect skill error ...cid:%lu, dupid:%u, sceneid:%u, effectid:%u ", cid, m_nDuplicateID, m_nSceneID, replaceSkillId);
			}
		}
	}	
	m_setInitEnter.clear();
}

void PestilenceDuplicate::CheckCharState()		//检查角色状态
{
	//先检查玩家 HP
	MAP_UINT64_INT8::iterator iter = m_mapCharCamp.begin();
	for (; iter != m_mapCharCamp.end(); ++iter)
	{
		CharIDType charId = iter->first;
		if (IsDown(charId))
		{
			continue;
		}
		Player *pPlayer = GetPlayer(charId);
		if (nullptr != pPlayer)
		{
			/*int32_t maxHp = pPlayer->GetAttr(C_MAX_HP);
			int32_t curHp = pPlayer->GetAttr(C_HP);
			int32_t downHp = (int32_t)(maxHp * 0.1);*/
		}
	}
}

//定时器更新
void PestilenceDuplicate::OnTimerUpdate(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_Update:
		{
			if ((int8_t)EDuplicateState::EDuplicateState_Begin == GetDuplicateState())
			{
				CheckInitEnter();
			}			
		}
		break;
	case ETimer_Clean:
		{
			OnCommon_CleanStateEnd();
		}
		break;
	case ETimer_Destory:
		{
			LogDebugFmtPrint("[logic] PestilenceDuplicate destory .... duplicateid:%u , sceneid:%u, mapid:%u ", m_nDuplicateID, m_nSceneID, m_nMapID);
			//回收
			OnCommon_DestoryStateEnd();
		}
		break;
	default:
		break;
	}

}
//执行事件
void PestilenceDuplicate::OnExecuteEvent(uint16_t nEventID, uint32_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD:
		{
		}
		break;
	case EVENT_ENTER_SCENE:
		{
		}
		break;
	case EVENT_UNDER_ATTACK:
		{
			if (nLen != sizeof(skillAttackEvent))
			{
				LogErrFmtPrint("[logic] PestilenceDuplicate::OnExecuteEvent nLen != sizeof(skillAttackEvent)...len:%d ,sceneid:%u, mapid:%u,  duplicateid:%u ", nLen, nSrcID, m_nMapID, m_nDuplicateID);
				return;
			}
			skillAttackEvent *pEvent = (skillAttackEvent*)pContext;
			if (IsInjectCamp(pEvent->attacker)
				&& pEvent->skillId == (uint32_t)m_cfg.injectCovertId)
			{
				LogDebugFmtPrint("[logic] PestilenceDuplicate::OnExecuteEvent....inject use skill....inject_cid:%lu, survivie_cid:%lu, skillid:%d, dupid:%u, sceneid:%u ",pEvent->attacker,pEvent->victim,m_cfg.injectCovertId,m_nDuplicateID,m_nSceneID);
				SurviveBeInject(pEvent->victim);
			}
			

		}
		break;
	default:
		break;
	}
}

void PestilenceDuplicate::OnReady_State()
{

}

void PestilenceDuplicate::OnBegin_State()
{
	//OnCommon_DupBeginState();
}

void PestilenceDuplicate::OnFinish_State()
{
	/*
	生还者奖励
	结算时，作为生还者身份，获得对抗的胜利
	按照副本内结算时的感染者数量，发放给每个生还者【（感染者数量/4）四舍五入取整】的份数的奖励
	离线/主动退出的感染者，结算时也算在感染者数量内
	感染者奖励
	结算时，作为感染者身份，获得对抗的胜利
	每个感染者，按照其所感染的生还者数量，发放（生还者数量+1）份数的奖励
	离线/主动退出的生还者，当其离线/主动退出时，此时所有感染者的所感染生还者数量+1
	需要实时记录每次对抗时，每个感染者所感染的生还者目标数量
	包括被感染后新增的感染者
	参与奖励
	对抗失败的一方，所发放的安慰奖	
	*/
	//副本结束


	//通用的副本结束处理
	OnCommon_DupFinishState();
	//瘟疫之战副本结束处理
	int8_t winCamp = PestilenceWinCamp();
	MAP_UINT64_INT8::iterator iter = m_mapCharCamp.begin();
	for (; iter != m_mapCharCamp.end(); ++iter)
	{
		CharIDType charId = iter->first;
		int8_t camp = iter->second;
		int32_t itemId = 0;
		int32_t rewardNum = 0;
		if (camp == winCamp)
		{
			if (EDupCampType_Inject == winCamp) //感染者胜利
			{
				itemId = m_cfg.injectItemId;
				rewardNum = GetInjectNum(charId) + 1; //每个感染者，按照其所感染的生还者数量，发放（生还者数量+1）份数的奖励
			}
			else //生还者胜利
			{
				//按照副本内结算时的感染者数量，发放给每个生还者【（感染者数量/4）四舍五入取整】的份数的奖励
				itemId = m_cfg.surviveItemId;
				rewardNum = (int32_t)round((float)m_maxInjectNum / 4);
			}
		}
		else
		{
			//失败方 奖励只有参与奖励
			itemId = m_cfg.attendItemId;
			rewardNum = 1;
		}
		if (itemId > 0 && rewardNum > 0)
		{
			LIST_ITEM lstItem;
			lstItem.clear();
			SItem item;
			item.nItemID = itemId;
			item.nNum = rewardNum;
			lstItem.push_back(item);
			//
			VEC_ITEM_PROTO_EX vecProtoEx;
			vecProtoEx.clear();
			SItemCond itemCond;
			g_GetDropMgr()->GetItemCond(charId, itemCond);
			if (g_GetItemMgr()->CreateItem(lstItem, vecProtoEx, itemCond))
			{
				if (camp == winCamp)
				{
					g_GetGMailMgr()->SendSystemMail(charId, m_cfg.szWinTopic, m_cfg.szWinContent, 0, 0, 0, 0, 0, vecProtoEx);
				}
				else
				{
					g_GetGMailMgr()->SendSystemMail(charId, m_cfg.szAttendTopic, m_cfg.szAttendContent, 0, 0, 0, 0, 0, vecProtoEx);
				}				
			}
			else
			{
				LogErrFmtPrint("[logic]  PestilenceDuplicate::OnFinish_State .. g_GetItemMgr()->CreateItem failed... cid:%lu,camp:%d, dupid:%u,sceneid:%u, wincamp:%d , itemid:%d, num:%d ", charId, camp, m_nDuplicateID, m_nSceneID, winCamp, itemId, rewardNum);
			}
		}
	}
}

void PestilenceDuplicate::OnFlop_State()
{
	//设置抽奖时间 15s
	//LogDebugFmtPrint("[logic] PestilenceDuplicate::OnDuplicateState_Flop....duplicateid:%u , sceneid:%u ", m_nDuplicateID, m_nSceneID);
	//OnCommon_DupFlopState();
}

void PestilenceDuplicate::OnClean_State()
{
	OnCommon_DupCleanState();
}

void PestilenceDuplicate::OnDestory_State()
{
	OnCommon_DupDestoryState();
}